﻿#region Usings

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

using Gonte.Wpf.Controls.ResourceManagers;

#endregion

namespace Gonte.Wpf.Controls.ViewModel
{
    /// <summary>
    /// The view model of a single item (leaf)
    /// </summary>
    public class ItemViewModel
        : IViewModel
        , INotifyPropertyChanged
        , IComparable
    {
        #region Constructors

        /// <summary>
        /// Used by ContentViewModel
        /// </summary>
        protected ItemViewModel(ItemViewModelInfo viewModelInfo)
        {
            ExceptionThrower.ThrowWhenNull("viewModelInfo", viewModelInfo);

            _viewModelInfo = viewModelInfo;
        }

        public ItemViewModel(ItemViewModelInfo viewModelInfo, IViewModel parent, object model)
        {
            ExceptionThrower.ThrowWhenNull("viewModelInfo", viewModelInfo);
            ExceptionThrower.ThrowWhenNull("parent", parent);
            ExceptionThrower.ThrowWhenNull("model", model);

            _viewModelInfo = viewModelInfo;
            _parent = parent;
            _model = model;
        }

        #endregion

        #region Methods

        public static void AddMenuItem(ContextMenu menu, ICommand command)
        {
            MenuItem item = new MenuItem();
            item.Command = command;
            menu.Items.Add(item);
        }

        public static void AddMenuItem(ContextMenu menu, string header, ICommand command)
        {
            MenuItem item = new MenuItem();
            item.Header = header;
            item.Command = command;
            menu.Items.Add(item);
        }

        #endregion

        #region Overridables

        public virtual ContextMenu CreateContextMenu()
        {
            if (null != _viewModelInfo.ContextMenuFactory)
            {
                return _viewModelInfo.ContextMenuFactory(_model);
            }

            return null;
        }

        protected virtual void UpdateIconSource()
        {
            _iconSource = ImageManager.GetImage(_viewModelInfo.IconUri);
            OnPropertyChanged("IconSource");
        }

        #endregion

        #region Properties

        public virtual bool IsExpanded
        {
            get { throw new NotImplementedException(); }
            set { /* throw new NotImplementedException(); */ }
        }

        public virtual object Model
        {
            get { return _model; }
            set { _model = value; }
        }

        public IViewModel Parent
        {
            get { return _parent; }
            set { _parent = value; }
        }

        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }

            set
            {
                if (value != _isSelected)
                {
                    _isSelected = value;
                    OnPropertyChanged("IsSelected");
                }
            }
        }

        public virtual bool IsChecked
        {
            get
            {
                return _isChecked;
            }

            set
            {
                if (value != _isChecked)
                {
                    _isChecked = value;
                    OnPropertyChanged("IsChecked");
                }
            }
        }

        public Visibility Visibility
        {
            get
            {
                return _visibility;
            }

            set
            {
                if (value != _visibility)
                {
                    _visibility = value;
                    OnPropertyChanged("Visibility");
                }
            }
        }

        public virtual string Label
        {
            get { return _label; }
            set { _label = value; }
        }

        /// <summary>
        /// Returns the icon image to be shown
        /// </summary>
        public BitmapImage IconSource
        {
            get { return _iconSource; }
            //set { _iconSource = value; }
        }

        #endregion

        #region Event handlers

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region IComparable Members

        public int CompareTo(object @object)
        {
            ItemViewModel viewModel = (ItemViewModel)@object;

            if (null != _viewModelInfo.ChildrenComparer)
            {
                return _viewModelInfo.ChildrenComparer(this, viewModel);
            }

            // No children comparer
            return _label.CompareTo(viewModel._label);
        }

        #endregion

        #endregion

        #region Selection changed

        internal void OnSelectionChanged(object sender, IViewModel viewModel)
        {
            IViewModel root = FindRoot();

            if (null != ((ItemViewModel)root)._selectionChanged)
            {
                ((ItemViewModel)root)._selectionChanged(this, new ViewModelEventArgs(viewModel));
            }
        }

        public SelectionChangedHandler SelectionChanged
        {
            get { return _selectionChanged; }
            set { _selectionChanged = value; }
        }

        public delegate void SelectionChangedHandler(object sender, ViewModelEventArgs args);

        private SelectionChangedHandler _selectionChanged;

        #endregion

        #endregion

        #region Helpers

        private IViewModel FindRoot()
        {
            if (null == _parent)
            {
                return this;
            }

            return ((ItemViewModel)_parent).FindRoot();
        }

        #endregion

        #region Fields

        protected ItemViewModelInfo _viewModelInfo;
        protected object _model;
        protected IViewModel _parent;
        private bool _isSelected;
        private bool _isChecked;
        private Visibility _visibility;
        protected BitmapImage _iconSource;
        protected string _label;

        #endregion
    }
}
